/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.semi.fw;

import com.semi.util.FileLogger;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Iterator;

/**
 *
 * @author liaoyq
 */
public class ConsoleThrd extends Thread {
    private volatile boolean isRun = false;
    private volatile boolean RunSignal = false;
    private final FileLogger mLogger= new FileLogger("com.semi.fw.ConsoleThrd");
//休眠间隔
    private long interval=1000l;
    protected CodeCenter mRoot = null;
    protected ArrayList mClients = new ArrayList();
    protected ByteBuffer mReadBuffer = ByteBuffer.allocate(1024);    
    public ConsoleThrd(CodeCenter root){
        mRoot = root;
    }
    public boolean isRuning(){
        return isRun;
    }    
    protected void removeClient(FwUser user){        
            //if( user.mKey!=null ) user.mKey.cancel();
            user.onClose();
            user.mChennel.close();
            //mClients.remove(user);
    }    
    protected void createClient(SocketChannel sc){
       // mLogger.info("client "+ sc.socket().getRemoteSocketAddress()+" up");
        FwUser user = new FwUser(new SocketWrapper(sc),mRoot);
        try{
            sc.configureBlocking(false);
            user.onConnected();
            mClients.add(user);
        }catch(Exception e){
            mLogger.info("client "+sc.socket().getRemoteSocketAddress()+" down",e);
            try{sc.close();}catch(Exception e2){}
        }
    }   
    public void run() { 
        mLogger.info("Thread start......");
        isRun = true;
        RunSignal = true;
        ServerSocketChannel ssc = null;
        try{
            ssc = ServerSocketChannel.open();  
            ServerSocket ss = ssc.socket();  
            // set no blocking  
            ssc.configureBlocking(false);             
            ss.bind(new InetSocketAddress(mRoot.ConsolePort()));
            mLogger.info("Listen success on "+mRoot.ConsolePort());
            //ssc.register(selector, SelectionKey.OP_READ);
        }catch(IOException e){
            mLogger.info("Listen failure",e);
            RunSignal = false;
        }
        SocketChannel sc = null;
        try{
        while (RunSignal) {  
        //dosomething
            sc = ssc.accept();
            if( sc!=null )      createClient(sc);            
            Iterator it = mClients.iterator();
            int k=0;
            while (it.hasNext()) {
                FwUser  user = (FwUser)it.next();
                if( user.mChennel.noValidate() ){
                    removeClient(user);
                    it.remove();
                    continue;
                }
                try{
                    //mReadBuffer.clear();                
                    String tmp = user.mChennel.readBlock(mReadBuffer);
                    if( tmp ==null ){
                        // 客户端已经断开连接.
                        removeClient(user);
                        it.remove();
                        continue;                    
                    }
                    if( tmp.length()==0 ){
                        if( user.isTimeout()){
                            user.onTimeOut();
                        }
                        continue;
                    }
                    k++;
                    //mLogger.info("read "+tmp.length());
                    user.onData(tmp);
                    if( user.IsExit() ){
                        removeClient(user);
                        it.remove();
                    }
                }catch(IOException e){
                    mLogger.info("client error",e);
                        removeClient(user);
                        it.remove();
                }
                // 清空buffer
                mReadBuffer.clear();                
            }
            
            if( k<1 ){
                try{
                    Thread.sleep(20);
                }catch(Exception e){}
            }
            //checkTimeout();
        }
        }catch(IOException e){
            mLogger.info("server socket error",e);
        }
        cleanup();
        if( ssc!=null ){
            try {
                ssc.close();
            } catch (IOException ex) {
            }
        }
        mLogger.info("Thread down completed");
        isRun = false;
    }  
    protected void cleanup(){
        mLogger.info("clean up all client");
        for(int i=0;i<mClients.size();i++){
            FwUser user =(FwUser) mClients.get(i);
            if( user.mChennel.isValidate()) {
                user.onClose();
                user.mChennel.close();
            }
        }
        mClients.clear();
    }
    public void closeWait() {  
        mLogger.info("console thread down begin....");
        this.RunSignal = false;
       // this.interrupt();
        while( isRun ){ 
            try {
                Thread.sleep(interval);
            } catch (InterruptedException ex) {
            }    
        }
        mLogger.info("console thread down completed");
    }        
}
